const express = require('express')
const app = require('../server')
const path = require('path')
const url = require('url')
const urlencode = require('urlencode')
const wechat = require('wechat')
const router = express.Router()
const axios = require('axios')
const tokenStore = require('../wechat/tokenStore')
const webTokenStore = require('../wechat/webTokenStore')
const {
  getUserProfile,
  getWebUserProfile,
  refreshWebAccessToken,
  downloadImg, createMenu,
  getMenu
} = require('../wechat/services')
const config = require('../wechat/config')
const redirect_origin = config.origin
const ticketStore = require('../wechat/ticketStore')

router.all('/', wechat(config,
      wechat
      .text(function (message, req, res, next) {
        res.reply('嗨～～')
      })
      .event(function (message, req, res, next) {
        const openid = req.query.openid
        const UserModel = app.models.UserModel

        if (message.Event === 'subscribe') {
          tokenStore.getAccessToken(config.appid, config.appSecret)
            .then(access_token => getUserProfile(access_token, openid))
            .then(userProfile =>
              UserModel
                .findOne({ where: { openid } })
                .then(user => user ? user : UserModel.createUser(userProfile))
            )
            .then(user => {
              res.reply('订阅成功')
              /*res.reply([{
                title: '你来我家接我吧',
                description: '这是女神与高富帅之间的对话',
                picurl: url.resolve(redirect_origin, user.avatar),
                url: 'http://nodeapi.cloudfoundry.com/'
              }]);*/
            })
            .catch(err => res.reply(''))
        }
      })
));

var GclientId = 1
router.get('/clientId', function(req, res, next) {
  res.send(String(GclientId++))
})

// Generate QR Code (URI)
// {clientId} tag one client binding wechat user & socket.clientId
// {tabelid} tag one table
// {source} default 'qr'
router.get('/generateQR', function(req, res, next) {
  const { clientId, tableId, source = 'qr', position } = req.query
  const appid = config.appid
  const appendParam = [`clientId=${clientId}`, `tableId=${tableId}`, `source=${source}`, `position=${position}`].join('&')
  const redirect_uri = urlencode(redirect_origin + '/wechat/login?' + appendParam)
  const url =
    'https://open.weixin.qq.com/connect/oauth2/authorize' +
    '?appid=' + appid +
    '&redirect_uri=' + redirect_uri +
    '&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect'

  res.redirect(url)
  // res.status(200).send(url)
})

// Wechat scan QR Code & login
// Should Tag clientId, tabelId, source [QR|...]
router.get('/login', function(req, res, next) {
  const { clientId, tableId, code, position } = req.query
  const UserModel = app.models.UserModel
  const Match = app.models.Match

  if (!code) {
    res.render('loginCallback', { success: false })
    return
  }

  webTokenStore.getWebAccessToken(config.appid, config.appSecret, code)
    .then(({ access_token, openid }) => getWebUserProfile(access_token, openid))
    .then(userProfile =>
      UserModel
        .findOne({ where: { openid: userProfile.openid } })
        .then(user => user ? user : UserModel.createUser(userProfile))
    )
    .then(user => {
      const bindUserData = Object.assign({}, user.__data, { position })
      app.bindSocket(clientId, bindUserData)
      // Make sure The device know who it is.
      // app.pushDataToClient('me', clientId, bindUserData)
      return Match.wechatJoin(user.__data, clientId, tableId, position)
    })
    .then( _ => res.render('loginCallback', { success: true }))
    .catch(err => {
      console.log(err)
      res.render('loginCallback', { success: false })
    })
})

router.get('/download', function(req, res, next) {
  const url = req.query.url
  const UserModel = app.models.UserModel

  UserModel
    .saveAvatar(url)
    .then(filename => res.send(filename))
    .catch(err => res.send(err))
})

// Note: just mock QR login
router.get('/test/QRlogin', function(req, res, next) {
  const { clientId, openid, tableId } = req.query
  const UserModel = app.models.UserModel
  const Match = app.models.Match

  UserModel
    .findOne({ where: { openid } })
    .then(user => {
      console.log('user', user)
      app.bindSocket(clientId, user.__data)
      // Make sure The device know who it is.
      app.pushDataToClient('me', clientId, user)
      Match.wechatJoin(user.__data, clientId, tableId)
      res.send(user)
    })
    .catch(err => res.send(err))
})

// Notes: subscribe public accout, record the user
router.get('/matches', function(req, res, next) {
  const { code, state } = req.query
  const UserModel = app.models.UserModel

  webTokenStore
    .getWebAccessToken(config.appid, config.appSecret, code)
    .then(({ openid }) => {
      return UserModel.findOne({ where: { openid }})
    })
    .then(user => {
      // res.send(user)
      res.render('layout')
    })
    .catch(err => res.send(err))
})

router.get('/board', function(req, res, next) {
  const { type, userid } = req.query
  const UserModel = app.models.UserModel
  const Match = app.models.Match

  UserModel
    .findOne({ where: { id: userid }})
    .then(user => Match.getBoard(user, type))
    .then(board => res.json(board))
    .catch(error => res.status(404).send({ error }))
})

router.get('/personalHome', function(req, res, next) {
  const { code } = req.query
  const UserModel = app.models.UserModel
  const Match = app.models.Match

  const userPromise = webTokenStore
    .getWebAccessToken(config.appid, config.appSecret, code)
    .then(({ openid }) => UserModel.findOne({ where: { openid } }))

  const matchPromise = userPromise
      .then(user => user ? Match.getBoard(user, 'xzdd') : null)
  const winRatioPromise = userPromise
      .then(user => Match.calcWinRatio(user))

  Promise.all([userPromise, matchPromise, winRatioPromise])
    .then(([user, board, winRatio]) => {
      res.render('personalHome', {
        user: user,
        board: {
          'xzdd': board
        },
        winRatio: winRatio
      })
    })
    .catch( err => {
      console.log(err)
      res.send(err)
    })
})

// router.get('/personalHome/:name', function(req, res, next) {
//   res.render('personalHome/' + req.params.name)
// })

router.get('/personalHome/match-records', function(req, res, next) {
  const { id, code } = req.query
  const UserModel = app.models.UserModel
  const Match = app.models.Match

  let userPromise = null

  if (id) {
    userPromise = UserModel.findOne({ where: { id } })
  } else if (code) {
    userPromise = webTokenStore.getWebAccessToken(config.appid, config.appSecret, code)
      .then(({ openid }) => UserModel.findOne({ where: { openid } }))
  } else {
    res.render('personalHome/match-records')
    return
  }

  userPromise
    .then(user => Match.statMatchesbByUser(user).then(matches => ([user, matches])))
    .then(([user, matches]) => {
      res.render('personalHome/match-records', { user, matches })
    })

  return
})

router.get('/personalHome/match-detail', function(req, res, next) {
  const { id, matchId } = req.query
  const UserModel = app.models.UserModel
  const Match = app.models.Match

  UserModel.findOne({ where: { id }})
    .then(user => Match.statMatchByUser(matchId, user))
    .then(games => {
      console.log('======> game ====')
      console.log(games)
      res.render('personalHome/match-detail', { games })
    })
})

router.get('/personalHome/mahjong-address', function(req, res, next) {
  res.render('personalHome/mahjong-address')
})

// Notes:
// Need to user Profile, specify needAuth
router.post('/menu/create', function(req, res, next) {
  console.log('====== createMenu ==========')
  const menuJSON = req.body
  const transformUrl = url => {
    return [
      'https://open.weixin.qq.com/connect/oauth2/authorize',
      '?appid=' + config.appid,
      '&redirect_uri=' + urlencode(redirect_origin + url),
      '&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect'
    ].join('')
  }

  menuJSON.button.forEach(button => {
    if (button.type === 'view' && button.needAuth) {
      button.url = transformUrl(button.url)
      delete button.needAuth
    }

    (button.sub_button || []).forEach(button => {
      if (button.type === 'view' && button.needAuth) {
        button.url = transformUrl(button.url)
        delete button.needAuth
      }
    })
  })

  tokenStore.getAccessToken(config.appid, config.appSecret)
    .then(access_token => createMenu(access_token, menuJSON))
    .then(msg => res.send(msg))
    .catch(err => res.send(err))
})

router.get('/menu/get', function(req, res, next) {
  tokenStore.getAccessToken(config.appid, config.appSecret)
    .then(access_token => getMenu(access_token))
    .then(menu => res.send(menu))
    .catch(err => res.send(err))
})

// Refresh web access_token
router.get('/refresh', function(req, res, next) {
  const refresh_token = req.query.refresh_token

  refreshWebAccessToken(config.appid, refresh_token)
    .then(response => {
      webTokenStore.saveWebAccessTokenStore(response)
      res.send(response)
    })
    .catch(err => {
      res.send('refresh failure')
    })
})

router.get('/MP_verify_XiYf4OMYeNALFMb3.txt', function(req, res, next) {
  res.sendFile(path.join(__dirname, '../wechat', 'MP_verify_XiYf4OMYeNALFMb3.txt'))
})

router.get('/test/board', function(req, res, next) {
  const openid = req.query.openid
  const UserModel = app.models.UserModel
  const Match = app.models.Match

  const userPromise = UserModel.findOne({ where: { openid } })
  const matchPromise = userPromise
      .then(user => user ? Match.getBoard(user) : null)

  Promise.all([userPromise, matchPromise])
    .then(([user, board]) => {
      if (user && board) {
        res.json({ user: user, board: board })
      }
    })
    .catch( err => {
      console.log(err)
      res.send(err)
    })
})


// Test calculate
router.get('/mock/board', function(req, res, next) {
  const playerId = req.query.playerId
  const Match = app.models.Match

  if (!playerId) {
    res.send('playerId required')
  }

  Match.getBoard({ id: playerId })
    .then(board => {
      res.json({ board })
    })
    .catch(err => {
      console.log(err)
      res.send({ error: '抛错' })
    })
})

router.get('/mock/winRatio', function(req, res, next) {
  const playerId = req.query.playerId
  const Match = app.models.Match
  if (!playerId) {
    res.send('playerId required')
  }

  Match.calculatelWinRatio({ id: playerId })
    .then(winRatio => res.send({ winRatio }))
    .catch(err => {
      console.log(err)
      res.send({ error: '抛错' })
    })

})

router.get('/mock/statMatchesbByUser', function(req, res, next) {
  const playerId = req.query.playerId
  const Match = app.models.Match
  if (!playerId) {
    res.send('playerId required')
  }

  Match.statMatchesbByUser({ id: playerId })
    .then(matches => res.send(matches))
    .catch(err => {
      console.log(err)
      res.send({ error: '抛错' })
    })
})


router.get('/sign', function (req, res) {
  const { link } = req.query

  ticketStore.getJsApiTicket(config.appid, config.appSecret)
    .then(ticket => ticketStore.sign(ticket, link.split('#')[0]))
    .then(_config => res.send(Object.assign(_config, { appid: config.appid })))
    .catch(error => res.send({ error }))
})

router.get('/test/reconnect', function(req, res, next) {
  const { matchId } = req.query
  const Match = app.models.Match

  if (!matchId) {
    res.send('matchId')
  }
  console.log(matchId)

  Match
    .findOne({
      where: { id: matchId },
      include: ['users'],
    })
    .then(match => {
      console.log('======== 成功 ========')
      // app.pushDataToClient('match', clientId , match)
      res.send(match)
    })
    .catch(err => {
      console.log('======== 失败 ========')
      console.log(err)
    })
})

module.exports = router
